package com.ssau.expert.core.impl;

import com.ssau.expert.core.model.Variable;
import com.ssau.expert.util.Names;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/**
 * Author: Sergey Saiyan
 * Created: 19.09.13 14:38
 */
public class VariableTable {

    protected Map<String, Variable> table;

    protected Stack<Variable> variableStack;

    public Stack getVariableStack() {
        return variableStack;
    }

    public Variable getVariable(String name) {
        return table.get(name);
    }

    public void putVariable(Variable variable) {
        if (variable.getName().isEmpty()) {
            throw new IllegalArgumentException("Variable name can not be null");
        }
        if (contains(variable.getName())) {
            throw new IllegalStateException(String.format("Variable '%s' is already present in the table", variable.getName()));
        }
        table.put(variable.getName(), variable);
    }

    public boolean contains(String name) {
        return table.containsKey(name);
    }

    public String getVariableInfo() {
        StringBuilder sb = new StringBuilder();
        for (Variable v : table.values()) {
            sb.append(v).append("\n");
        }
        return sb.toString();
    }

    protected void resetTable() {
        variableStack.clear();
        for (Variable v : table.values()) {
            v.setValue(null);
            v.setInitialized(false);
        }
    }

    private static VariableTable instance = new VariableTable();

    private VariableTable() {
        table = new HashMap<>();
        variableStack = new Stack<>();
        defineVars();
    }

    private void defineVars() {

        Variable resultVar = new Variable();
        resultVar.setClazz(List.class);
        resultVar.setName(Names.RESULT);
        resultVar.setTarget(true);
        putVariable(resultVar);

        Variable profileVar = new Variable();
        profileVar.setName(Names.PROFILE);
        profileVar.setClazz(String.class);
        putVariable(profileVar);

        Variable autoVar = new Variable();
        autoVar.setClazz(Integer.class);
        autoVar.setName(Names.DISTANCE);
        putVariable(autoVar);

        Variable stuffVar = new Variable();
        stuffVar.setClazz(Integer.class);
        stuffVar.setName(Names.STUFF);
        putVariable(stuffVar);
    }

    public static VariableTable get() {
        return instance;
    }
}
